﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using personalplaner.core.errorhandling;
using personalplaner.core.zip;
using System.Xml;
using personalplaner.core.sql;
using personalplaner.business.common;
using personalplaner.common.mvvm;
using personalplaner.common.mvvm.mediator;
using System.Windows;

namespace personalplaner.databasewizard.services
{
    public interface IDatabaseService
    {
        void Execute(string odbcSource, string user, string password, string database);

        Mediator Mediator { get; }
    }

    public abstract class DatabaseServiceBase : IDatabaseService
    {
        #region Mediator

        static readonly Mediator mediator = new Mediator();

        public Mediator Mediator
        {
            get { return mediator; }
        }

        #endregion

        public DatabaseServiceBase(/*LogonData logData,*/ string xmlPath, string zipFileName)
        {
            //this.logData = logData;

            string dir = AppDomain.CurrentDomain.BaseDirectory + "SQL\\Log\\";

            try
            {
                if (!Directory.Exists(dir))
                    Directory.CreateDirectory(dir);
            }
            catch (Exception)
            {
                try
                {
                    dir = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "\\Personalplaner\\SQL\\Log\\";
                    if (!Directory.Exists(dir))
                        Directory.CreateDirectory(dir);
                }
                catch (Exception) { }
            }

            ActionLogger.LogName = string.Format("{0}DB-{1}_{2}-{3}-{4}.log", dir, DateTime.Now.Date.ToShortDateString(), DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second);
            ActionLogger.LoggMessage(MessageType.SQL, string.Format("Begin Datenbank generierung- {0}", DateTime.Now.ToString()));
            ExtractFiles(zipFileName);
            ReadFilelist(xmlPath);
        }

        public abstract void Execute(string odbcSource, string user, string password, string database);

        IList<string> _sqlFilenames;
        public IList<string> SqlFileNames
        {
            get
            {
                return _sqlFilenames;
            }
        }

        Dictionary<string, string> _sqlFileVersions;
        public Dictionary<string, string> SqlFileVersions
        {
            get
            {
                return _sqlFileVersions;
            }
        }

        DatabaseSettings _settings;
        public DatabaseSettings Settings
        {
            get
            {
                return _settings;
            }
            set
            {
                _settings = value;
            }
        }

        protected bool IsNoError
        {
            get;
            set;
        }
        

        private void ExtractFiles(string zipFileName)
        {
            GZipDecompress.Decompress(@"SQL\", ExtractPath, zipFileName);
            ActionLogger.LoggMessage(MessageType.SQL, string.Format("Extract sql files from {0}", zipFileName));
        }

        private void ReadFilelist(string xmlPath)
        {
            _sqlFilenames = new List<string>();
            _sqlFileVersions = new Dictionary<string, string>();

            var doc = new XmlDocument();
            doc.Load("SQL\\sqlfiles.xml");
            XmlNodeList nodes = doc.SelectNodes(xmlPath);
            foreach (XmlNode node in nodes)
            {
                SqlFileNames.Add(node.Attributes["name"].Value.ToString());
                SqlFileVersions.Add(node.Attributes["name"].Value.ToString(), node.Attributes["version"].Value.ToString());
            }
        }

        private string ExtractPath
        {
            get
            {
                string path = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "\\Personalplaner\\SQL\\tmp\\";
                if (!Directory.Exists(path))
                    Directory.CreateDirectory(path);

                return path;
            }
        }

        public bool ExecuteSqlFiles(int index)
        {
            if (index < SqlFileNames.Count && File.Exists(ExtractPath + SqlFileNames[index]))
            {
                string script;
                FileInfo file = new FileInfo(ExtractPath + SqlFileNames[index]);
                script = file.OpenText().ReadToEnd();
                string[] scripts = PrepareScripts(script);

                for (int i = 0; i < scripts.Length; i++)
                {
                    if (scripts[i] != string.Empty)
                    {
                        if (CheckForPrints(scripts[i]))
                        {
                            ActionLogger.LoggMessage(MessageType.SQL, scripts[i].Trim());
                            //if (OnOutput != null)
                            //    OnOutput(scripts[i].Trim());
                            Mediator.NotifyColleagues<string>("AppendOutputString", scripts[i].Trim());
                        }
                        else
                        {
                            IsNoError = SimpleQuerry.Execute(Settings, scripts[i]);

                            if (!IsNoError)
                            {
                                //if (OnError != null)
                                //{
                                    ActionLogger.LoggMessage(MessageType.SQL_ERROR, "Fehler beim generieren der Datenbank aufgetreten.");
                                    Logger.ToXML("SQLWizz", "WZDatabase.ExecuteSqlFiles(int)", scripts[i]);
                                    MessageBox.Show("Es ist ein Fehler aufgetreten.\nFür genauere Informationen schauen sie bitte im Logfile nach.", "Fehler", MessageBoxButton.OK);
                                //    OnError("Es ist ein Fehler aufgetreten.\nFür genauere Informationen schauen sie bitte im Logfile nach.", "Fehler");

                                //}
                                return false;
                            }
                        }
                    }
                }
                return true;
            }
            return false;
        }

        private static string[] PrepareScripts(string script)
        {
            var statements = script.Replace("go", ";");
            statements = statements.Replace("GO", ";");
            return statements.Split(';');
        }

        private static bool CheckForPrints(string script)
        {
            string tmp = script.TrimStart();
            if (tmp.StartsWith("print", true, null))
                return true;

            return false;
        }
    }
}
